Repository navigation
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
⏭️ Performance benchmarks were skippedPerf benchmarks (CodSpeed) are opt-in on pull requests — they no longer run on every push. They always run automatically after merge to To run them on this PR, do any of the following, then push a commit (or re-run CI):
|
Binary size checks passed✅ 7 passed
Generated by |
…roject load; parallel LSP sweep Three fixes for the "12 threads = 1.18x" cold-check scaling wall, diagnosed by comparing against ty/ruff's salsa usage (whose driver pattern ours already matches): - Prime wave: compute every file's PPIR semantic index across workers BEFORE fanning out per-file checks. Whole-package aggregate queries (package_items / namespace_items) fold over every file's index, and every file's check demands them - on a cold database the first worker to claim the aggregate memo computed parse+lowering+indexing for the entire project inline on one thread while all other workers parked on that memo's sync slot. With per-file indexes primed the aggregate fold is cheap and workers stay busy. Also replaces the old first-file serial warm-up, which warmed the builtin package (compiler2_all_files orders builtins first), not the user package. - Bulk project load: add_or_update_files registers all sources with ONE project-file-list write; the per-file path cloned and re-set the whole files Vec and bumped the salsa revision once per file (O(files^2) copies during initial load). Source reads now happen across worker threads, preserving discovery order so FileId assignment and diagnostic ordering are unchanged. - The LSP diagnostics candidate now checks files through the shared order-preserving parallel checker (under the held source guard - the same exclusion the serial loop relied on), so every per-edit path inherits the parallelism and the prime wave. check_files_parallel returns per-file results in input order so the LSP can zip them back to documents; the flat collector delegates. Measured (Apple Silicon, 12 cores): - cold pure check, 295k LOC: 7.4s -> 2.8s wall (1.2 -> 2.4+ cores) - cold check+seed, 295k LOC: 10.5s -> 4.4s; 59k LOC: ~0.9s - LSP edit->diagnostics: 250 files 464 -> 172ms; 500 files 1.7s -> 176ms; 1000 files 5.5s -> 209ms (now ~flat in project size) - LSP load test: burst storms + sustained churn at 250/1000 files, zero crashes, stable RSS, convergence after every storm Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01V4oee6wrCHzXH6mM2h8eJo
c2da018 to
f214619
Compare
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…itor latency (BoundaryML#4105) Consolidated stack (supersedes BoundaryML#4098, BoundaryML#4100, BoundaryML#4101 — their commits are all contained here, rebased onto current canary). Seven commits, reviewable independently, in dependency order. ## What this does A ground-up performance pass on the compiler driven by head-to-head benchmarking against tsgo (native TypeScript) and `go build` on semantically identical generated corpora (1.5k–295k LOC), followed by root-cause profiling of every gap found. ### 1. `perf(compiler2)`: kill the two cold-compile quadratics; parallelize the cache-path check - The package-wide Jinja type environment was rebuilt inside every `check_file` call (O(N²)) — and twice per compile via `get_bytecode`'s error gate. Now a memoized salsa query (`jinja_base_types`) + skipped entirely for files with no prompts. - `ProjectDatabase` handle clones deep-copied two N-entry PathBuf maps; the parallel drivers clone ~1.55N handles per compile (quadratic CPU + peak RSS). Now Arc-wrapped, O(1). - `baml check`/`run` routed through a serial diagnostics collector while the parallel one sat unreachable next to it. Now shared. - The LSP proves the project error-free once (`get_bytecode_unchecked`), and its diagnostics candidate now includes package-level diagnostics — cross-file name conflicts previously **never reached the editor at all**. ### 2. `feat(cli)`: `baml pack` uses the bytecode cache; `baml check` seeds it Pack was fully cold on every invocation (no cache participation at all); check reused but never wrote, so check-only workflows never warmed. Now one warm cache serves check → run → test → pack. ### 3–4. `build` + `fix(ci)`: hardware SHA-2 (`sha2/asm`, gated off MSVC), doc-link fix The warm path hashes ~hundreds of MB of unit payloads per run; it was on the software SHA fallback. ### 5. `perf(compiler2)`: prime wave, bulk project load, parallel LSP sweep Cold parallel check scaled 1.18× on 12 cores: every file's check demands whole-package aggregates, and the first worker to claim that memo computed parse+index for the entire project inline while all other workers parked on the sync slot (diagnosed against ty/ruff's salsa usage; interventionally verified). Per-file indexes are now primed across workers before fan-out. Project load stops re-writing the file list per file (O(files²)) and reads sources in parallel (FileId order preserved). The LSP candidate uses the shared order-preserving parallel checker. ### 6. `perf(cache)`: warm no-op checks stop re-proving the cache A warm no-op check cost the same as a full recompute: the throws-gate safety compare re-parsed every file, and seeding read+hashed 78MB of unit payloads for metadata. Now: the gate is skipped when the dirty partition is provably empty (a value compared against itself), throws fragments live verbatim in the manifest so a no-op check opens **zero** unit payloads, and units load in parallel (manifest order preserved) only when a delta means relink will need them. Both verify oracles (`BAML_CACHE_VERIFY` full compare + always-on 1-in-32 sampled re-derive) now check the manifest copy — exactly what is served. Design was adversarially reviewed; the unsound variant (fact-space throws compare) was rejected and every real edit still takes the full runtime-space gate. ### 7. `refactor(cli)`: one shared `ProjectSession` for every project-loading command check/run/test/pack/describe/grep/generate each hand-rolled a drifting subset of the same preamble — the root cause of "pack forgot the cache" and "describe never primes." One implementation; commands declare `CacheUse::{ReadWrite, ReadWriteTests, ReadOnly, Off}`. Introspection installs seeds only on a no-delta plan (provable tautology) and derives honestly otherwise. ## Measured impact (Apple Silicon, 12 cores, hyperfine) | | before | after | |---|--:|--:| | cold check, 295k LOC | 21–46 s (126 s CPU, 5.3 GB RSS) | **6.6 s** (~13 s CPU, 2.7 GB) | | cold check, 59k LOC | 3.3 s | **1.24 s** | | warm no-op check, 295k / 59k | 7.2 s / 3.2 s | **2.0–2.6 s / 0.4–0.6 s** | | `run` after check (59k / 295k) | full compile | **0.12 s / 0.65 s** (cache hit) | | `pack` after check (59k / 295k) | 1.7 s / 40.5 s (always cold) | **0.19 s / 0.87 s** (cache hit) | | LSP edit→diagnostics (250/500/1000 files) | 0.46 / 1.7 / 5.5 s | **179 / 192 / 216 ms** (flat) | | `describe`, 295k / 59k LOC | 6.3 s / 716 ms | **2.6 s / 402 ms** | Cold compile scaling is now ~linear in project size (was quadratic: 5× code cost 33× CPU), verified to 8000 modules. ## Verification - Diagnostics byte-identical to the pre-change binary (error-heavy corpus, cold + warm) at each stage. - Cache soundness: `BAML_CACHE_VERIFY=1` honest-recompile compare (no-op + after-edit) and forced `BAML_CACHE_SAMPLED_VERIFY=1` across edit sequences — all pass; 43 bytecode-cache oracle tests updated and green. - LSP load-tested: 50-edit multi-file burst storms + sustained ~17 edits/s churn at 250/1000 files — zero crashes, stable RSS, convergence after every storm. - Full stack green in CI (doc, Windows incl. MSVC sha2 gating, size gate, all SDK matrices). ## Deliberate trade-offs - Cold `check` at mid-size projects (~15–30k LOC) is ~10% slower than before: it now emits + stores once to warm the cache; every later check/run/pack is served warm. - A warm *edit* check re-emits and stores (that is what buys the instant run/pack); at 295k LOC the edit path remains ~6–9 s — the known remaining floor, tracked separately. - A unit file deleted out from under a warm cache is not detected on a no-op run; the next compile that needs it falls back to a byte-identical full compile. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01V4oee6wrCHzXH6mM2h8eJo <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * CLI commands now share a consistent, cache-aware project session workflow, including lenient read-only sessions for inspection when configuration is missing. * **Performance** * Faster project loading and diagnostics checking via parallel per-file processing. * Improved bytecode-cache reuse by avoiding unnecessary payload hashing/loading, including a fast “no-delta” warm path. * **Bug Fixes** * Fixed callable-throws fragment seeding and verification for warm “no-delta” runs. * Improved package-level diagnostics handling during compilation and error-gating behavior. * **Chores** * Improved build robustness for cryptography acceleration on MSVC targets. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Fable 5 <[email protected]>
Stacked on #4098. Fixes the "12 threads = 1.18× speedup" wall, diagnosed by comparing our salsa usage against ty/ruff's (our driver pattern was already identical to theirs — the problem was one query shape).
What
package_items/namespace_items) fold over every file's index; on a cold db the first worker to claim that memo computed parse+lower+index for the entire project inline on one thread while all other workers parked on the memo's sync slot. Also retires the old first-file warm-up, which warmed the builtin package, not the user package.add_or_update_fileswrites the project file list once (the per-file path re-cloned the whole Vec and bumped the salsa revision per file — O(files²) during load); source reads are parallel with discovery order preserved (FileId assignment and diagnostic ordering unchanged).End-user impact (measured)
Editor latency is now ~flat in project size.
Verification
baml_project/bex_project/baml_cli.Not in this PR: ty-style snapshot+cancellation for the LSP (blocked on the
panic = "abort"release profile — cancellation requires unwinding; needs a product decision), and the warm-edit floor (throws-gate + unit loads; separate reviewed design).🤖 Generated with Claude Code
https://claude.ai/code/session_01V4oee6wrCHzXH6mM2h8eJo